#ifndef BOT_H_
#define BOT_H_

#include "State.h"
#include "MiniState.h"
#include "fieldgenerator.h"

#include <map>
#include <vector>
#include <utility>
#include <deque>

class PathQueueEntry {
public:
    Location antLoc;
    std::stack<int> path;
public:
    PathQueueEntry(const Location& loc,
		   const std::stack<int>& antpath):antLoc(loc),path(antpath) {}
    bool operator < (const PathQueueEntry& other) const{
	return path.size() > other.path.size();
    }
};

typedef std::priority_queue<PathQueueEntry> PathQueue;

/*
    This struct represents your bot in the game of Ants
*/

enum BATTLEMETHOD {
    DMG_BASED=0,
    FOCUS_BASED
};

class Bot
{
private:
    State state;
    PotentialField field;
    std::map< int , std::vector<Location> > squadList;
    std::map< Location,bool > inSquad;
    std::map< Location,bool > processedAnts;
    std::vector<Location> explorers;
public:
    Bot();

    void playGame();    //plays a single game of Ants

    void makeMoves();   //makes moves for a single turn
    void endTurn();     //indicates to the engine that it has made its moves    
private:

    //Squad management  functions
    void buildSquads();
    void moveSquad(const int& squad_id);
    bool isInSquad(const Location& ant) const;
    void clearSquads();
    void printSquad(const int& squad_id) ;


    bool findNearbyValidLoc(const Location& loc,Location& validLoc);
    bool isFoodAdjacent(const Location& loc);
    void safeMakeMove(const Location& ant,int direction);

    //multi source BFS based exploration
    void antMakeExplorer(const Location& loc);
    void squadMakeExplorers(const int& squad_id);
    void multiSourceBFSHelper(const State::BFSQueueMode& queueMode);

    void multiSourceBFSExplore();

    bool shouldAttack() const;;

    //miniMax support for combat
    int miniMaxDecision(MiniState& miniState,int player_id,const Location& target,
                        std::map<Location,int>& bestMove);
    int maxValue(MiniState miniState,int player_id,int depth,const Location& target,
                 std::map<Location,int>& maxMove,int alpha,int beta);
    int minValue(MiniState miniState,int player_id,int depth,const Location& target,
                 std::map<Location,int>& maxMove,int alpha,int beta);
    bool moveSquadTo2(const std::vector<Location>::iterator& start,
                      const std::vector<Location>::iterator& end,
                     const Location& loc,int& moveCnt);
    std::vector<std::map<Location,int> > generateMoveVectors(MiniState& miniState,int player_id,
                                                             const Location& target,bool reversePlayer);

    //crappy random Sampling moves
    float runMoveList(MiniState miniState,int player_id,const std::map<Location,int>& moveList);
    std::map<Location,int> randomSample(MiniState& miniState,int player_id);

};

#endif //BOT_H_
